package com.huarui.saleInvoice.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.ewaf.framework.model.ListModel;
import org.ewaf.framework.service.BaseService;
import org.ewaf.framework.util.BeanUtil;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;

import com.huarui.code.dao.ICodeGenericDao;
import com.huarui.code.model.CodeGeneric;
import com.huarui.partner.dao.IPartnerDao;
import com.huarui.partner.model.Partner;
import com.huarui.partner.service.PartnerService;
import com.huarui.payInvoice.model.PayInvoice;
import com.huarui.payInvoice.util.PayInvoiceMessageEnum;
import com.huarui.receivable.dao.IReceivableDao;
import com.huarui.receivable.model.Receivable;
import com.huarui.saleInvoice.dao.ISaleInvoiceDao;
import com.huarui.saleInvoice.model.SaleInvoice;
import com.huarui.saleInvoice.util.SaleInvoiceMessageEnum;
import com.huarui.saleInvoiceItem.dao.ISaleInvoiceItemDao;
import com.huarui.saleInvoiceItem.model.SaleInvoiceItem;
import com.huarui.user.model.SessionMessage;
import com.huarui.user.security.UserHolder;

public class SaleInvoiceService extends BaseService {
	private final static Logger logger = Logger.getLogger(SaleInvoiceService.class);
	private IReceivableDao iReceivableDao;
	private PartnerService partnerService;
	private IPartnerDao partnerDao;
	private ICodeGenericDao iCodeGenericDao;
	private ISaleInvoiceItemDao iSaleInvoiceItemDao;
	private ISaleInvoiceDao getDao(){
		return (ISaleInvoiceDao) this.dao;
	}
	@SuppressWarnings("unchecked")
	public List<Map> pagingByCondition(ListModel lm,Map map){
		Integer total = getDao().getCountByConditions(map);
		lm.setTotal(total);
		map.put("listModel", lm);
		List result = this.getDao().getListByConditions(map);
		lm.setResult(result);
		return result;
	}
	@SuppressWarnings("unchecked")
	public List<Map> getListByCondition(Map map){
		List result = this.getDao().getListByConditions(map);
		return result;
	}
	@SuppressWarnings("unchecked")
	public Map getObjByCondition(Map map){
		List list = this.getListByCondition(map);
		Map result=null;
		if(list!=null&&list.size()==1){
			result=(Map) list.get(0);
			return result;
		}else{
			return null;
		}
	}
	@SuppressWarnings("unchecked")
	public Map<String,Object> getSaleInvoiceById(final Integer id,final SessionMessage sm) {
		List<Map> result = null;
		Map<String, Object> resultMap = new HashMap<String, Object>();
		try {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("id", id);
			map.put("companyId", sm.getCompanyId());
			result = getListByCondition(map);
		} catch (Exception e) {
			logger.error("应收款查询出错", e);
			resultMap.put(SaleInvoiceMessageEnum.SUCCESS.getMsg(),SaleInvoiceMessageEnum.ERROR_MSG_DATABASE.getMsg());
			return resultMap;
		}
		if (result!=null&&result.size() > 0) {
			resultMap.put("data", result.get(0));
			if(result.get(0).containsKey("customerId")){
				Partner partner=(Partner) partnerService.getById(result.get(0).get("customerId"));
				partner=partnerService.getComboProperties(partner);
				resultMap.put("partner", partner);
			}
		}
		resultMapInfo(resultMap);
		return resultMap;
	}
	public Map<String,Object> createFormPayable(final String receivableIds,final Integer customerId,final SessionMessage sm){
		final Map<String, Object> resultMap = new HashMap<String, Object>();
		try {
			transactionTemplate.execute(new TransactionCallback() {
				@SuppressWarnings("unchecked")
				@Override
				public Object doInTransaction(TransactionStatus status) {
					String[] strs=receivableIds.split(",");
					Map map=new HashMap();
					map.put("ids", strs);
					List list=iReceivableDao.getListByConditions(map);
					resultMap.put("receivableList", list);
					if(customerId!=null){
						Partner partner=(Partner) partnerService.getById(customerId);
						if(partner!=null){
							resultMap.put("partner", partner);
						}
					}
					return null;
				}
			});
		} catch (Exception e) {
			logger.error("创建收款单出错",e);
			resultMap.put(SaleInvoiceMessageEnum.SUCCESS.getMsg(),SaleInvoiceMessageEnum.ERROR_MSG_DATABASE.getMsg());
			return resultMap;
		}
		resultMap.put(SaleInvoiceMessageEnum.SUCCESS.getMsg(),SaleInvoiceMessageEnum.RESULT_TYPE_SUCCESS.getMsg());
		return resultMap;
	}
	/* 保存 */
	public Map<String,Object> saveSaleInvoice(final SaleInvoice saleInvoiceTemp,
			final List<SaleInvoiceItem> list, final SessionMessage sm) {
		final Map<String,Object> resultMap=new HashMap<String, Object>();
		// 修改数据
		try {
			transactionTemplate.execute(new TransactionCallback() {
				@Override
				public Object doInTransaction(TransactionStatus status) {
					saveSaleInvoiceAndItems(saleInvoiceTemp, list, sm,resultMap,status);
					return null;
				}
			});
		} catch (Exception e) {
			logger.error("保存应收款出错",e);
			resultMap.put(SaleInvoiceMessageEnum.SUCCESS.getMsg(), SaleInvoiceMessageEnum.ERROR_MSG_DATABASE.getMsg());
			return resultMap;
		}
		resultMapInfo(resultMap);
		return resultMap;
	}
	@SuppressWarnings("unchecked")
	private SaleInvoice saveSaleInvoiceAndItems(SaleInvoice saleInvoiceTemp,
			List<SaleInvoiceItem> list, SessionMessage sm,Map<String,Object> resultMap,TransactionStatus status) {
		Map map = new HashMap();
		SaleInvoice saleInvoice=null;
		if (saleInvoiceTemp.getId() != null) {
			map.put("id", saleInvoiceTemp.getId());
			map.put("companyId", sm.getCompanyId());
			saleInvoice=(SaleInvoice) getDao().getById(map);
			if(saleInvoice==null){
				resultMap.put(SaleInvoiceMessageEnum.SUCCESS.getMsg(), SaleInvoiceMessageEnum.ERROR_MSG_NOTEXIST.getMsg());
				status.isRollbackOnly();
				return null;
			}
			saleInvoice.setCustomerId(saleInvoiceTemp.getCustomerId());
			saleInvoice.setCodeOfSeller(saleInvoiceTemp.getCodeOfSeller());
			saleInvoice.setGmtActualReceive(saleInvoiceTemp.getGmtActualReceive());
			saleInvoice.setInvoiceType(saleInvoiceTemp.getInvoiceType());
			saleInvoice.setAmount(saleInvoiceTemp.getAmount());
			getDao().update(saleInvoice);
		} else {
			saleInvoice=new SaleInvoice();
			saleInvoice.setCurrentorId(sm.getUserId());
			saleInvoice.setCompanyId(sm.getCompanyId());
			saleInvoice.setGmtCreate(new Date());
			saleInvoice.setStatus(0);
			saleInvoice.setCreator(sm.getUserId());
			saleInvoice.setCode(iCodeGenericDao.getNewCode(sm.getCompanyId(),CodeGeneric.SALEINVOICE));
			//
			saleInvoice.setCustomerId(saleInvoiceTemp.getCustomerId());
			saleInvoice.setCodeOfSeller(saleInvoiceTemp.getCodeOfSeller());
			saleInvoice.setGmtActualReceive(saleInvoiceTemp.getGmtActualReceive());
			saleInvoice.setInvoiceType(saleInvoiceTemp.getInvoiceType());
			saleInvoice.setAmount(saleInvoiceTemp.getAmount());	
			saleInvoice.setCurrentorId(sm.getUserId());
			getDao().create(saleInvoice);
		}
		map.clear();
		map.put("saleInvoiceId", saleInvoice.getId());
		List<Map> queryList=iSaleInvoiceItemDao.getListByCondition(map);
		Map<Integer,SaleInvoiceItem> saleInvItemMap=new HashMap<Integer, SaleInvoiceItem>();
		for(Map item:queryList){
			SaleInvoiceItem saleInvoiceItem=new SaleInvoiceItem();
			BeanUtil.populateBean(saleInvoiceItem, item);
			saleInvItemMap.put(saleInvoiceItem.getId(), saleInvoiceItem);
		}
		for (SaleInvoiceItem invoiceItem : list) {
			if (invoiceItem.getId() == null) {
				invoiceItem.setCompanyId(sm.getCompanyId());
				invoiceItem.setSaleInvoiceId(saleInvoice.getId());
				iSaleInvoiceItemDao.create(invoiceItem);
			} else if(invoiceItem.getId() != null){
				iSaleInvoiceItemDao.update(invoiceItem);
				saleInvItemMap.remove(invoiceItem.getId());
			} 
		}
		Set<Integer> removeSet= saleInvItemMap.keySet();
		List<Integer> removeList=new ArrayList<Integer>();
		for(Integer id:removeSet){
			removeList.add(id);
		}
		map.clear();
		map.put("ids", removeList);
		iSaleInvoiceItemDao.deleteByCondition(map);
		map.clear();
		map.put("saleInvoiceId", saleInvoice.getId());
		List<Map> itemList=iSaleInvoiceItemDao.getListByCondition(map);
		BigDecimal amount=getPayInvoiceAmount(itemList);
		saleInvoice.setAmount(amount);
		getDao().update(saleInvoice);
		putSaleInvoiceResult(saleInvoice.getId(), sm.getCompanyId(), resultMap);
		resultMap.put("saleInvoiceItemList", list);
		return saleInvoice;
	}
	private BigDecimal getPayInvoiceAmount(List<Map> itemList){
		BigDecimal amount=BigDecimal.ZERO;
		for(Map o:itemList){
			BigDecimal paid=(BigDecimal) o.get("received");
				amount=amount.add(paid);
		}
		return amount;
	}
	@SuppressWarnings("unchecked")
	public void putSaleInvoiceResult(Integer id,Integer companyId,Map<String,Object> resultMap){
		Map<String,Object> map=new HashMap<String, Object>();
		map.put("id", id);
		map.put("companyId", companyId);
		Map saleInMap = this.getObjByCondition(map);
		resultMap.put("saleInvoice", saleInMap);
	}
	public Map<String, Object> submitSaleInvoice(String saleInvoiceJson,String saleInvoiceItemsJson) {
		final SessionMessage sm=UserHolder.getCurrentSessionMessage();
		final Map<String, Object> resultMap = new HashMap<String, Object>();
		try {
			final SaleInvoice	saleInvoiceTemp = (SaleInvoice) JSONObject.toBean(JSONObject.fromObject(saleInvoiceJson), SaleInvoice.class);
			final List<SaleInvoiceItem> list=(List<SaleInvoiceItem>) JSONArray.toCollection(JSONArray.fromObject(saleInvoiceItemsJson), SaleInvoiceItem.class);
			transactionTemplate.execute(new TransactionCallback() {
				@SuppressWarnings("unchecked")
				@Override
				public Object doInTransaction(TransactionStatus status) {
					SaleInvoice saleInvoice=saveSaleInvoiceAndItems(saleInvoiceTemp, list, sm,resultMap,status);
					if(saleInvoice!=null){
						saveReceivable(list);
						savePartner(saleInvoice);
						saleInvoice.setStatus(SaleInvoice.STATUS_FORMAL);
						saleInvoice.setGmtReceive(new Date());
						saleInvoice.setReceiver(sm.getUserId());
						getDao().update(saleInvoice);
						putSaleInvoiceResult(saleInvoice.getId(), sm.getCompanyId(), resultMap);
						/*if(resultMap.containsKey("saleInvoice")){
							Map payInv=(Map) resultMap.get("saleInvoice");
							if(payInv.containsKey("status")){
								payInv.put("status", SaleInvoice.STATUS_FORMAL);
							}
						}*/
						//resultMap.put("payInvoice", payInvoice);
					}
					return null;
				}
			});
		} catch (Exception e) {
			logger.error("提交收款单出错",e);
			resultMap.put(PayInvoiceMessageEnum.SUCCESS.getMsg(),PayInvoiceMessageEnum.ERROR_MSG_DATABASE.getMsg());
			return resultMap;
		}
		resultMapInfo(resultMap);
		return resultMap;
	}
	private void savePartner(SaleInvoice saleInvoice){
		Map<String,Object> map=new HashMap<String, Object>();
		map.put("ownerId", saleInvoice.getCompanyId());
		map.put("id", saleInvoice.getCustomerId());
		map.put("isLock", true);
		Partner partner=partnerService.getPartnerByCondition(map);
		partner.setReceived((partner.getReceived()==null?BigDecimal.ZERO:partner.getReceived()).add(saleInvoice.getAmount()==null?BigDecimal.ZERO:saleInvoice.getAmount()));
		partner.setUnreceived((partner.getUnreceived()==null?BigDecimal.ZERO:partner.getUnreceived()).subtract(saleInvoice.getAmount()==null?BigDecimal.ZERO:saleInvoice.getAmount()));
		partnerDao.updatePartnerAmountById(partner);
	}
	@SuppressWarnings("static-access")
	private void saveReceivable(List<SaleInvoiceItem> list) {
		Map<String,Object> map=new HashMap<String, Object>();
		for (SaleInvoiceItem invoiceItem : list) {
			map.clear();
			map.put("id", invoiceItem.getReceivableId());
			Receivable receivable = (Receivable) iReceivableDao.getById(map);
			receivable.setReceived(receivable.getReceived()==null?BigDecimal.ZERO:receivable.getReceived().add(invoiceItem.getReceived()==null?BigDecimal.ZERO:invoiceItem.getReceived()));
			if (receivable.getReceivable().compareTo(receivable.getReceived()) == 0) {
				receivable.setStatus(receivable.STATUS_COMPLETE);
				receivable.setGmtReceived(new Date());
			}
			iReceivableDao.update(receivable);
		}
	}
	public Map<String,Object> delete(final Integer id,final SessionMessage sm) {
		final Map<String, Object> resultMap = new HashMap<String, Object>();
		try {
			transactionTemplate.execute(new TransactionCallback() {
				@SuppressWarnings("unchecked")
				@Override
				public Object doInTransaction(TransactionStatus status) {
					Map map = new HashMap();
					map.put("id", id);
					map.put("companyId", sm.getCompanyId());
					getDao().deleteByCondition(map);
					map.clear();
					map.put("saleInvoiceId", id);
					iSaleInvoiceItemDao.deleteByCondition(map);
					return null;
				}
			});
		} catch (Exception e) {
			logger.error("删除收款单出错",e);
			resultMap.put(SaleInvoiceMessageEnum.SUCCESS.getMsg(),SaleInvoiceMessageEnum.ERROR_MSG_DATABASE.getMsg());
			return resultMap;
		}
		resultMapInfo(resultMap);
		return resultMap;
	}
	public Map<String,Object> release(final Integer id,final SessionMessage sm){
		final Map<String, Object> resultMap = new HashMap<String, Object>();
		try {
			transactionTemplate.execute(new TransactionCallback() {
				@Override
				public Object doInTransaction(TransactionStatus status) {
					Map<String,Object> map=new HashMap<String,Object>();
					map.put("id",id);
					map.put("companyId", sm.getCompanyId());
					SaleInvoice saleInvoice=(SaleInvoice) getDao().getById(map);
					if(saleInvoice==null){
						resultMap.put(SaleInvoiceMessageEnum.SUCCESS.getMsg(),SaleInvoiceMessageEnum.ERROR_MSG_NOTEXIST.getMsg());
						status.isRollbackOnly();
						return null;
					}
					saleInvoice.setCurrentorId(null);
					getDao().update(saleInvoice);
					Map retSaleInvoice=getObjByCondition(map);
					resultMap.put("data", retSaleInvoice);
					return null;
				}
			});
		} catch (Exception e) {
			logger.error("释放收款单出错",e);
			resultMap.put(SaleInvoiceMessageEnum.SUCCESS.getMsg(),SaleInvoiceMessageEnum.ERROR_MSG_DATABASE.getMsg());
			return resultMap;
		}
		resultMapInfo(resultMap);
		return resultMap;
	}
	public Map<String,Object> receive(final Integer id,final SessionMessage sm){
		final Map<String, Object> resultMap = new HashMap<String, Object>();
		try {
			transactionTemplate.execute(new TransactionCallback() {
				@Override
				public Object doInTransaction(TransactionStatus status) {
					Map<String,Object> map=new HashMap<String,Object>();
					map.put("id",id);
					map.put("companyId", sm.getCompanyId());
					SaleInvoice saleInvoice=(SaleInvoice) getDao().getById(map);
					if(saleInvoice==null){
						resultMap.put(SaleInvoiceMessageEnum.SUCCESS.getMsg(),SaleInvoiceMessageEnum.ERROR_MSG_NOTEXIST.getMsg());
						status.isRollbackOnly();
						return null;
					}
					saleInvoice.setCurrentorId(sm.getUserId());
					getDao().update(saleInvoice);
					return null;
				}
			});
		} catch (Exception e) {
			logger.error("接收收款单出错",e);
			resultMap.put(SaleInvoiceMessageEnum.SUCCESS.getMsg(),SaleInvoiceMessageEnum.ERROR_MSG_DATABASE.getMsg());
			return resultMap;
		}
		resultMapInfo(resultMap);
		return resultMap;
	}
	private void resultMapInfo(Map<String,Object> resultMap){
		if(!resultMap.containsKey(SaleInvoiceMessageEnum.SUCCESS.getMsg())){
			resultMap.put(SaleInvoiceMessageEnum.SUCCESS.getMsg(),SaleInvoiceMessageEnum.RESULT_TYPE_SUCCESS.getMsg());
		}
	}

	public void setiReceivableDao(IReceivableDao iReceivableDao) {
		this.iReceivableDao = iReceivableDao;
	}
	public void setPartnerService(PartnerService partnerService) {
		this.partnerService = partnerService;
	}
	public void setiCodeGenericDao(ICodeGenericDao iCodeGenericDao) {
		this.iCodeGenericDao = iCodeGenericDao;
	}
	public void setiSaleInvoiceItemDao(ISaleInvoiceItemDao iSaleInvoiceItemDao) {
		this.iSaleInvoiceItemDao = iSaleInvoiceItemDao;
	}
	public void setPartnerDao(IPartnerDao partnerDao) {
		this.partnerDao = partnerDao;
	}
	
}
